#include <QtGui>

#include "GlobPref.h"
#include "DataModel.h"
#include "WidSybilView.h"
#include "FactoryView.h"
// directly used dialogs
#include "DlgTimeSlice.h"
#include "DlgServerCon.h"
#include "DlgDebug.h"
#include "DlgAbout.h"
//
#include "WinMain.h"
#include "scImpl.h"

#define FCT "WinMain::WinMain"
WinMain::WinMain(QWidget *parent)
    : QMainWindow(parent), viewClosure(false)
{
	ctrc(Trc::SETUP,APP,FCT)<<"app started "<<QThread::currentThreadId()<<endl;
	setWindowTitle(tr("Sybil Project Management"));
	statusBar()->addPermanentWidget(&permStat);

	// force the creation of a server connection through first call of DataModel::get()
	connect(DataModel::get(), SIGNAL(statusTextSig(QString)), this, SLOT(statusTextSl(QString)));

	QMenu *fileMenu = menuBar()->addMenu(tr("&File"));
	exitAct=fileMenu->addAction(tr("E&xit"));
	exitAct->setStatusTip(tr("Exit the application"));
	connect(exitAct, SIGNAL(triggered()), this, SLOT(close()));

	QMenu *viewMenu = menuBar()->addMenu(tr("&View"));
	FactoryView *vf(FactoryView::get());
	vector<int> types(vf->getViewTypes());
	viewMapper = new QSignalMapper(this);
	connect(viewMapper, SIGNAL(mapped(int)), this, SLOT(addViewSl(int)));
	for(vector<int>::const_iterator it(types.begin()); it!=types.end(); ++it)
	{
		QAction * act(viewMenu->addAction(vf->getDisplayName(*it)));
		act->setStatusTip(vf->getDescription(*it));
		viewMapper->setMapping(act, *it);
		connect(act, SIGNAL(triggered()), viewMapper, SLOT(map()));
	}
	viewMenu->addSeparator();
	viewCloseAct=viewMenu->addAction(tr("&close a view"));
	viewCloseAct->setStatusTip(tr("close a view (or pane) by selecting it"));
	viewCloseAct->setShortcut(QKeySequence(tr("Ctrl+F4")));
	connect(viewCloseAct, SIGNAL(triggered()), this, SLOT(viewCloseSl()));

	QMenu *toolMenu = menuBar()->addMenu(tr("&Tools"));
	timeSliceAct=toolMenu->addAction(tr("set &time-slicing"));
	timeSliceAct->setStatusTip(tr("define for which time or version to view base- and plan-data"));
	timeSliceAct->setShortcut(QKeySequence(tr("Ctrl+T")));
	connect(timeSliceAct, SIGNAL(triggered()), this, SLOT(timeSliceSl()));
	toolMenu->addSeparator();
	garbageCollectAct=toolMenu->addAction(tr("&garbage collection"));
	garbageCollectAct->setStatusTip(tr("Force an instant garbage collection cycle. "));
	connect(garbageCollectAct, SIGNAL(triggered()), DataModel::get(), SLOT(forceGarbageCollectSl()));
	serverDataAct=toolMenu->addAction(tr("configure &server"));
	serverDataAct->setStatusTip(tr("Set the connection parameters of the server"));
	connect(serverDataAct, SIGNAL(triggered()), this, SLOT(serverDataSl()));

	QMenu *helpMenu = menuBar()->addMenu(tr("&Help"));
	timeInfoAct=helpMenu->addAction(tr("&time information"));
	timeInfoAct->setStatusTip(tr("Display various time-related data"));
	connect(timeInfoAct, SIGNAL(triggered()), this, SLOT(timeInfoSl()));
	debugAct=helpMenu->addAction(tr("&debug settings"));
	debugAct->setStatusTip(tr("Modify trace and log settings"));
	connect(debugAct, SIGNAL(triggered()), this, SLOT(debugDlgSl()));
	debugDataAct=helpMenu->addAction(tr("show debug &information"));
	debugDataAct->setCheckable(true);
	debugDataAct->setChecked(GlobPref::get()->getDebugData());
	debugDataAct->setStatusTip(tr("Make database key and other technical data visible on the GUI"));
	connect(debugDataAct, SIGNAL(triggered()), this, SLOT(debugDataActSl()));
	helpMenu->addSeparator();
	aboutAct=helpMenu->addAction(tr("&about this program"));
	aboutAct->setStatusTip(tr("Show the About box of this program"));
	connect(aboutAct, SIGNAL(triggered()), this, SLOT(aboutDlgSl()));
	aboutQtAct=helpMenu->addAction(tr("About &Qt"));
	aboutQtAct->setStatusTip(tr("Show the Qt library's About box"));
	connect(aboutQtAct, SIGNAL(triggered()), qApp, SLOT(aboutQt()));

	center=new QSplitter(Qt::Horizontal, this);
	setCentralWidget(center);
	QSettings settings;
	QList<QVariant> vws(settings.value("views/show").toList());
	ctrc(Trc::SETUP,APP,FCT)<<"restoring "<<vws.count()<<" views "<<endl;
	for(QList<QVariant>::const_iterator it(vws.begin()); it!=vws.end(); ++it)
	{
		int view(it->toInt());
		ctrc(Trc::SETUP,APP,FCT)<<"restoring view "<<view<<endl;
		addViewSl(view);
	}

	statusBar()->showMessage(tr("Ready"));
	statusTextPermSl();
}

#undef FCT
#define FCT "WinMain::~WinMain"
WinMain::~WinMain()
{
	ctrc(Trc::SETUP,APP,FCT)<<endl;
	QList<QVariant> vws;
	for(int i(0); i<center->count(); ++i)
	{
		WidSybilView * view(static_cast<WidSybilView *>(center->widget(i)));
		if(view)
		{
			int viewId(view->getViewId());
			ctrc(Trc::SETUP,APP,FCT)<<"saving view "<<view<<" (type "<<viewId<<")"<<endl;
			vws << QVariant(viewId);
		}
		else
			ctrc(Trc::SETUP,APP,FCT)<<"ignoring index "<<i<<endl;
	}
	QSettings settings;
	settings.setValue("views/show", QVariant(vws));
	settings.sync();
}

/*
#undef FCT
#define FCT "WinMain::showEvent"
void WinMain::showEvent(QShowEvent * event)
{
}
*/

#undef FCT
#define FCT "WinMain::checkViewClosureSl"
void WinMain::checkViewClosureSl(WidSybilView * view)
{
	if(!viewClosure)
		return;
	view->close();
	setCursor(Qt::ArrowCursor);
	viewClosure=false;
	//here count still says one more than expected... but it works out fine later
	//ctrc(Trc::WORK,APP,FCT)<<"splitter now has "<<center->count()<<" views"<<endl;
	for(int i(0); i<center->count(); ++i)
		center->widget(i)->setEnabled(true);
}

#undef FCT
#define FCT "WinMain::statusTextSl"
void WinMain::statusTextSl(QString text)
{
	statusBar()->showMessage(text);
}

#undef FCT
#define FCT "WinMain::statusTextPermSl"
void WinMain::statusTextPermSl()
{
	permStat.setText(tr("@ ")+DataModel::get()->getDeadlineQ().toString(QString("d.MMM.yyyy hh:mm"))+tr(" PV ? "));
}

#undef FCT
#define FCT "WinMain::addViewSl"
void WinMain::addViewSl(int viewType)
{
	center->addWidget(FactoryView::get()->create(viewType, this));
}

#undef FCT
#define FCT "WinMain::viewCloseSl"
void WinMain::viewCloseSl()
{
	if(!center->count())
		QMessageBox::warning(this, tr("Close View Info"),
			tr("Currently there is no open view."));
	else
	{
		if(viewClosure)
		{
			setCursor(Qt::ArrowCursor);
			viewClosure=false;
			for(int i(0); i<center->count(); ++i)
				center->widget(i)->setEnabled(true);
		}
		else
		{
			if(QMessageBox::Ok==QMessageBox::information(this, tr("Close View Info"),
				tr("After confirming this dialog click on the view you want to close."),
				QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Ok))
			{
				setCursor(Qt::CrossCursor);
				viewClosure=true;
				for(int i(0); i<center->count(); ++i)
					center->widget(i)->setEnabled(false);
			}
		}
	}
}

#undef FCT
#define FCT "WinMain::timeSliceSl"
void WinMain::timeSliceSl()
{
	// ctrc(Trc::WORK,APP,FCT)<<"entity"<<entity<<endl;
	DlgTimeSlice dlg(this);
	if(dlg.exec()==QDialog::Rejected)
	{
		ctrc(Trc::WORK,APP,FCT)<<"dialog canceled"<<endl;
		return;
	}
	DataModel::get()->setDeadline(dlg.getDeadline()); // includes updating
	statusTextPermSl();
}

#undef FCT
#define FCT "WinMain::timeInfoSl"
void WinMain::timeInfoSl()
{
	// toTime_t converts to UTC automatically
	// setTimeSpec changes the reference frame without adjusting date or
	//   time values, thus modifying the absolute point in time described by
	//   the object
	// fromTime_t creates a local time object
	QString fmt("yyyy-MM-dd hh:mm:ss");
	QDateTime loc(QDateTime::currentDateTime());
	QDateTime utc(loc.toUTC());
	QDateTime ttStart(QDateTime::fromTime_t(0));
	QString txt;
	txt =tr("Local time: ")			+loc.toString(fmt)+" ("+GlobPref::QtTimeSpec2Txt(loc.timeSpec())+")\n";
	txt+=tr("UTC time: ")			+utc.toString(fmt)+" ("+GlobPref::QtTimeSpec2Txt(utc.timeSpec())+")\n";
	txt+=tr("time_t (always UTC): ")+QString::number(utc.toTime_t())+'\n';
	txt+=tr("local time_t base: ")	+ttStart.toString(fmt)+" ("+GlobPref::QtTimeSpec2Txt(ttStart.timeSpec())+")\n";
	QMessageBox::information(this, tr("Time Information"), txt);
}

#undef FCT
#define FCT "WinMain::serverDataSl"
void WinMain::serverDataSl()
{
	ctrc(Trc::SETUP,APP,FCT)<<"start"<<endl;
	DlgServerCon dlg(this);
	if(dlg.exec()==QDialog::Rejected)
	{
		ctrc(Trc::WORK,APP,FCT)<<"dialog canceled"<<endl;
		return;
	}
}

#undef FCT
#define FCT "WinMain::debugDlgSl"
void WinMain::debugDlgSl()
{
	ctrc(Trc::SETUP,APP,FCT)<<"start"<<endl;
	DlgDebug dlg(this);
	if(dlg.exec()==QDialog::Rejected)
	{
		ctrc(Trc::WORK,APP,FCT)<<"dialog canceled"<<endl;
		return;
	}
}

#undef FCT
#define FCT "WinMain::debugDataActSl"
void WinMain::debugDataActSl()
{
	GlobPref *gp(GlobPref::get());
	gp->setDebugData(!(gp->getDebugData()));
	debugDataAct->setChecked(gp->getDebugData());
}

#undef FCT
#define FCT "WinMain::aboutDlgSl"
void WinMain::aboutDlgSl()
{
	ctrc(Trc::SETUP,APP,FCT)<<"start"<<endl;
	DlgAbout dlg(this);
	if(dlg.exec()==QDialog::Rejected)
	{
		ctrc(Trc::WORK,APP,FCT)<<"dialog canceled"<<endl;
		return;
	}
}
